

#include <string.h>
#include "BSP_Delay.h"
#include "BSP_RFIO.h"
#include "contactless.h"
#include <WCI.h>
#include <WCIPrivate.h>
#include "Fifo.h"
#include "CardMemPrivate.h"

#include <Card.h>
#include <CardPort.h>
#include <CardPortPrivate.h>

#include "nfc663.h"


static unsigned char Read_Reg(unsigned char reg_add) {
    return RFIO_Read(reg_add);
}

static unsigned char Read_Reg_All(unsigned char *reg_value) {
    unsigned char  i;
    for (i=0; i<64; i++){
		reg_value[i] = RFIO_Read(i);
	}
    return WCI_S_OK;
}
/*************************************************************/
/*函数名：	    Write_Reg				         */
/*功能：	    写寄存器操作				 */
/*								 */
/*输入参数：	reg_add，寄存器地址；reg_value，寄存器数值	 */
/*返回值：	    WCI_S_OK						 */
/*				WCI_S_Hardware				 */
/*************************************************************/
static unsigned char Write_Reg(unsigned char reg_add,unsigned char reg_value) {
	RFIO_Write(reg_add, reg_value);
    return WCI_S_OK;
}

/*************************************************************/
/*函数名：	    Set_BitMask									 */
/*功能：	    置位寄存器操作								 */
/*输入参数：	reg_add，寄存器地址；mask，寄存器置位		 */
/*返回值：	    WCI_S_OK											 */
/*				WCI_S_Hardware										 */
/*************************************************************/
static unsigned char Set_BitMask(unsigned char reg_add,unsigned char mask) {
    unsigned char result;
    unsigned char val = Read_Reg(reg_add) | mask;
    result=Write_Reg(reg_add, val);  // set bit mask
    return result;
}

/*   C L E A R _   B I T   M A S K   */
/*-------------------------------------------------------------------------
    清零寄存器位操作
-------------------------------------------------------------------------*/
static unsigned char Clear_BitMask(unsigned char reg_add,unsigned char mask) {
    unsigned char  result;
    unsigned char val = Read_Reg(reg_add) & ~mask;
    result=Write_Reg(reg_add, val);  // clear bit mask
    return result;
}



/*************************************************************/
/*函数名：	    Read_FIFO									 */
/*功能：	    读取FIFO  									 */
/*															 */
/*输入参数：	length，读取数据长度						 */
/*输出参数：	*fifo_data，数据存放指针					 */
/*返回值：	    											 */
/*															 */
/*************************************************************/
static void Read_FIFO(unsigned char length,unsigned char *fifo_data) {
	RFIO_ReadSequence(FIFODataReg, fifo_data, length);
}
/*************************************************************/
/*函数名：	    Write_FIFO									 */
/*功能：	    写入FIFO  									 */
/*															 */
/*输入参数：	length，读取数据长度；*fifo_data，数据存放指针*/
/*输出参数：												 */
/*返回值：	    											 */
/*															 */
/*************************************************************/
static void Write_FIFO(unsigned char length,unsigned char *fifo_data) {
	RFIO_WriteSequence(FIFODataReg, fifo_data, length);
}
/*************************************************************/
/*函数名：	    Clear_FIFO									 */
/*功能：	    清空FIFO  									 */
/*															 */
/*输入参数：	无											*/
/*输出参数：												 */
/*返回值：	    WCI_S_OK											 */
/*				WCI_S_Hardware										 */
/*************************************************************/
static unsigned char Clear_FIFO(void) {
    Set_BitMask(FIFOLevelReg,0x80);//清除FIFO缓冲
    if (RFIO_Read(FIFOLevelReg)==0)
        return WCI_S_OK;
    else
        return WCI_S_Hardware;
}



/*
WS1850 的定时器时钟频率为6.78MHz ，
在此，我们按13.56MHz计算 ，因此时间等待时间增加了一倍。
*/
static void MH663_SetWaitTime(uint32_t fc) {
    /*
    	Time = (Prescaler * 2 + 1) * Reload + 1
    	Reload 越大计时越精确
    */
    uint8_t RegTmode;
    uint32_t Prescale;
    uint32_t Counter;
    uint32_t CountUnit;
    uint32_t Time;

    if(fc != 0) {
        Time = fc - 1;
    } else {
        Time = 0;
    }

    Prescale = Time / 0xFFFF;

    if((Time & 0xFFFF) != 0) { //余数不为0
        Prescale++;
    }

    Prescale /= 2;

    CountUnit = 2 * Prescale + 1;
    Counter = Time / CountUnit;

    if((Time % CountUnit) != 0) { //余数不为0
        Counter++;
    }

    if(Prescale > 4095) {
        Counter = 65535;
        Prescale = 4095;
    }

    RegTmode = Read_Reg(TModeReg);
    RegTmode &= 0xF0;
    RegTmode |= ((Prescale >> 8) & 0x0F);
    Write_Reg(TModeReg, RegTmode);
    
    Write_Reg(TPrescalerReg, Prescale & 0xFF);
    Write_Reg(TReloadRegH, (Counter >> 8) & 0xFF);
    Write_Reg(TReloadRegL, Counter & 0xFF);

}


void WCI_Delay_Fc(unsigned int fc){
	unsigned int us = fc / 13 + 1;
	BSP_Delay_us(us);
}


#if 0
unsigned char Pcd_ConfigISOType(unsigned char type) {

	if(type < 3){
		MH663_SetConfig(fm17ConfigTable[type]);
		return WCI_S_OK;
	}
	return WCI_S_Hardware;
}
#endif 


/*   F   M 1 7 5   X   X _   S O F T   R E S E T   */
/*-------------------------------------------------------------------------
    MH663 软复位
-------------------------------------------------------------------------*/
#if 0
unsigned char  MH663_SoftReset(void) {
    Write_Reg(CommandReg,SoftReset);//

    while(Read_Reg(CommandReg)==SoftReset);
    return WCI_S_OK;

}
#endif 

unsigned char MH663_HardReset(void) {
    RFIO_SetReset(1);
    BSP_Delay_ms(10);
    RFIO_SetReset(0);
    BSP_Delay_ms(10);
    return WCI_S_OK;
}

unsigned char MH663_SoftPowerdown(void) {
    if (Read_Reg(CommandReg)&0x10) {
        Clear_BitMask(CommandReg,0x10);//退出低功耗模式
        return WCI_S_Hardware;
    } else
        Set_BitMask(CommandReg,0x10);//进入低功耗模式
    return WCI_S_OK;
}


unsigned char MH663_HardPowerdown(unsigned char mode) {	
    RFIO_SetReset(1);
    return WCI_S_OK;

}

static int MH663_SetMode(WCI* wci, int mode){
	
	mode &= ~ WCI_ForceMark;
	switch(mode){
	case WCI_Mode_A: {
		pcd_config('A');
	}
	break;
	case WCI_Mode_B:{
		pcd_config('B');
	}
	break;
	default :
		return -1;
	}
	wci->mode = mode;
	BSP_Delay_ms(1);
	return 0;
}



static int MH663_Config(WCI* wci, int cfg){
#if 0
	if(wci->config == cfg){
		return 0;
	}
#endif 
	cfg &= ~ WCI_ForceMark;
	switch(cfg){
	case WCI_Cfg_Short:{		
		write_reg(BitFramingReg,0x07);	// Tx last bytes = 7
		clear_bit_mask(TxModeReg, BIT7); //不使能发送crc
		clear_bit_mask(RxModeReg, BIT7); //不使能接收crc
		clear_bit_mask(Status2Reg, BIT3);//清零MF crypto1认证成功标记
	}
	break;

	case WCI_Cfg_Anti:{
		write_reg(BitFramingReg,0x00);	// // Tx last bits = 0, rx align = 0
		clear_bit_mask(TxModeReg, BIT7); //不使能发送crc
		clear_bit_mask(RxModeReg, BIT7); //不使能接收crc
	}
	break;
	
	case WCI_Cfg_Sel:
	case WCI_Cfg_RATS:
	case WCI_Cfg_HaltA:
	case WCI_Cfg_ExchangeA:{
		write_reg(BitFramingReg,0x00);	// // Tx last bits = 0, rx align = 0
		set_bit_mask(TxModeReg, BIT7); //使能发送crc
		set_bit_mask(RxModeReg, BIT7); //使能接收crc
	}
	break;

	case WCI_Cfg_RfOn:{
		pcd_antenna_on();
	}
	break;
	
	case WCI_Cfg_RfOff:{
		pcd_antenna_off();
	}
	break;
	default:
		return -1;
	}
#if 0
	wci->config = cfg;
#endif 
	BSP_Delay_ms(1);
	return 0;
}

int MH663_Aligned(WCI* wci, unsigned int txBits, unsigned int rxPos){
	unsigned char val = rxPos << 4 | txBits;
	val &= 0x7F;
	clear_bit_mask(BitFramingReg, TxLastBits | RxAlign);
	set_bit_mask(BitFramingReg, val); // tx lastbits , rx align
    return 0;
}



//fill chip FIFO full or no more data
static int MH663_WriteBuffer(WCI* wci){
	unsigned int i;
	unsigned int length = WCI_FifoLength(wci);
	unsigned int space = 64 - Read_Reg(FIFOLevelReg);
	unsigned int wlen = length > space ? space : length;
	uint8_t ch;	
	
	for(i = 0; i < wlen; ++i){
		if(WCI_ReadFifo(wci, &ch, 1)){
			Write_FIFO(1, &ch);
		}
		else{
			break;
		}
	}
	return i;
}

static int MH663_ReadBuffer(WCI* wci){
	unsigned int i;
	unsigned int space = WCI_FifoSpace(wci);
	unsigned int level = Read_Reg(FIFOLevelReg);
	unsigned int rlen = space > level ? level : space;
	uint8_t ch;	
	
	for(i = 0; i < rlen; ++i){
		Read_FIFO(1, &ch);
		if(!WCI_WriteFifo(wci, &ch, 1)){
			break;
		}
	}
	return i;
}

static int MH663_Authen(WCI* wci, uint8_t cmd, WciTime_T* time, void* param){	
	unsigned char irq;
	int result;
	MfAuthParam_T* mfauth = (MfAuthParam_T*)param;
	uint8_t txBuf[16];
	uint8_t tlen = 0;
    if(Clear_FIFO() != WCI_S_OK){
		return WCI_S_Unknow;
    }

	txBuf[tlen++] = mfauth->keyType;
	txBuf[tlen++] = mfauth->block;
	memcpy(&txBuf[tlen], mfauth->keys, sizeof(mfauth->keys));
	tlen += sizeof(mfauth->keys);
	memcpy(&txBuf[tlen], mfauth->uid, sizeof(mfauth->uid));
	tlen += sizeof(mfauth->uid);
	
    MH663_SetWaitTime(time->waitTime);
    Write_Reg(WaterLevelReg,0x20);//设置FIFOLevel=32字节
    Write_Reg(ComIrqReg,0x7F);//清除IRQ标志

	Write_FIFO(tlen, txBuf);
    Write_Reg(CommandReg, PCD_AUTHENT);
	Set_BitMask(BitFramingReg, 0x80);//启动发送
    Set_BitMask(TModeReg,0x80);//自动启动定时器

    while(1) { //循环判断中断标识
		irq = Read_Reg(ComIrqReg);//查询中断标志

		if(irq&0x10)	//IdelIRq  command寄存器为空闲，指令操作完成
		{
			result = WCI_S_OK;
			break;
		}
		if(irq&0x01) {	//TimerIRq  定时器时间用尽
		    result = WCI_S_Timeout;
		    break;
		}
		if((Read_Reg(TxControlReg) & 0x03) == 0){
			result = WCI_S_Unknow;
			break;
		}
	}
	if(result == WCI_S_OK){
		//判断加密标志位，确认认证结果
		if((Read_Reg(Status2Reg) & 0x08) == 0){
			result = WCI_S_Protocol;
		}
	}
    Set_BitMask(ControlReg,0x80);     // stop timer now
    Write_Reg(CommandReg,PCD_IDLE);
    Clear_BitMask(BitFramingReg,0x80);//关闭发送
	return result;
}

static int MH663_CmdExchange(WCI* wci, uint8_t cmd, WciTime_T* time, void* param){
    unsigned char  result;
    unsigned char  rx_temp=0;//临时数据字节长度
    unsigned char  rx_len=0;//接收数据字节长度
    unsigned char  lastBits=0;//接收数据位长度
    unsigned char  irq;
	uint8_t tlen = WCI_FifoLength(wci);
	uint8_t level = 48;
	WciBits_T* bits = (WciBits_T*) param;
	int ret;
	
    WCI_Delay_Fc(time->guardTime);
    MH663_SetWaitTime(time->waitTime);
    Write_Reg(WaterLevelReg,level);//设置FIFOLevel=48字节
    Write_Reg(ComIrqReg,0x7F);//清除IRQ标志
    Set_BitMask(TModeReg,0x80);//自动启动定时器
	MH663_Aligned(wci, bits->lastTx, bits->lastRx);
	ret = MH663_WriteBuffer(wci);
	tlen -= ret;
    Write_Reg(CommandReg,PCD_TRANSCEIVE);
	Set_BitMask(BitFramingReg,0x80);//启动发送

    while(1) { //循环判断中断标识
        irq = Read_Reg(ComIrqReg);//查询中断标志

		if((irq&0x04)&&(tlen>0)) { //LoAlertIrq + 发送字节数大于0
			ret = MH663_WriteBuffer(wci);
			tlen -= ret;
			Write_Reg(ComIrqReg,0x04);//清除LoAlertIrq
		}
		if(irq&0x08) {	//HiAlertIRq
			if((irq&0x40)&&(tlen==0)) { //TxIRq	+ 待发送长度为0 + FIFO长度大于32
				ret = MH663_ReadBuffer(wci);
				rx_len += ret;
			}
		}
		if((irq&0x20)&&(tlen==0)) {	//RxIRq=1
#if 0
			if(Read_Reg(Status2Reg) < 2){
				result=WCI_S_OK;
				break;
			}
#endif 
			result=WCI_S_OK;
			break;
		}
		if(irq&0x01) {	//TimerIRq  定时器时间用尽
            result=WCI_S_Timeout;
            break;
        }
		if((Read_Reg(TxControlReg) & 0x03) == 0){
			result = WCI_S_Unknow;
			break;
		}
    }

	if(result == WCI_S_OK){ // read data in FIFO
		rx_temp=Read_Reg(FIFOLevelReg);
		lastBits = Read_Reg(ControlReg) & 0x07;
		bits->lastRx = lastBits;
		if ((rx_temp==0)&&(lastBits>0))	{
		//如果收到长度未满1个字节，则设置接收长度为1个字节
			uint8_t ch;
			
			rx_temp=1;
			Read_FIFO(1, &ch);
			WCI_WriteFifo(wci, &ch, 1);
		}
		else{
			MH663_ReadBuffer(wci);
		}
	}	

    if(result == WCI_S_OK){ // check errors
        unsigned char err = Read_Reg(ErrorReg);
        if(err & CollErr){
			result = WCI_S_Coll;
        }
		else
		if(err & CrcErr){
			result = WCI_S_Crc;
		}
        else
		if(err & ParityErr){
			result = WCI_S_Parity;
		}
        else
        if(err){
			result = WCI_S_Hardware;
        }
    }

    Set_BitMask(ControlReg,0x80);     // stop timer now
    Write_Reg(CommandReg,PCD_IDLE);
    Clear_BitMask(BitFramingReg,0x80);//关闭发送
	Clear_FIFO();
    return result;
}

int MH663_Command(WCI* wci, uint8_t cmd, WciTime_T* time, void* param){
	if(cmd == WCI_Cmd_Exchagne){
		return MH663_CmdExchange(wci, cmd, time, param);
	}
	if(cmd == WCI_Cmd_Authen){
		return MH663_Authen(wci, cmd, time, param);
	}
	return -1;
}


static const WCIOps opsMH663 = {
	.setMode = MH663_SetMode,
	.config = MH663_Config,
	.command = MH663_Command,
};


WCI wciMH663 = {
	.ops = &opsMH663,
	.name = "MH663",
	.support = 0x03,
	.mode = -1,
	.config = -1,
};




#if 0
unsigned char Read_Ext_Reg(unsigned char reg_add) {
    Write_Reg(0x0F,0x80+reg_add);
    return Read_Reg(0x0F);
}

unsigned char Write_Ext_Reg(unsigned char reg_add,unsigned char reg_value) {
    Write_Reg(0x0F,0x40+reg_add);
    Write_Reg(0x0F,0xC0+reg_value);
    return WCI_S_OK;
}

unsigned char Set_Ext_BitMask(unsigned char reg_add,unsigned char mask) {
    unsigned char result;
    result=Write_Ext_Reg(reg_add,Read_Ext_Reg(reg_add)|mask);
    return result;
}


unsigned char Clear_Ext_BitMask(unsigned char reg_add,unsigned char mask) {
    unsigned char result;
    result=Write_Ext_Reg(reg_add,Read_Ext_Reg(reg_add)&(~mask));
    return result;
}
#endif 


static CardPort mh663Port;


void MH663_Init(void) {
	mh663Port.nCards = 0;
	mh663Port.maxCard = 1;
	mh663Port.typeMask = 1 << Card_T_CpuA | 1 << Card_T_CpuB | 1 << Card_T_Mifare;
	mh663Port.name = "MH663";
	mh663Port.pdata = (void*) &wciMH663;
    MH663_HardReset();
	pcd_reset();
    BSP_Delay_ms(10);
	Write_Reg(ControlReg, 0x10); //设置为读卡器模式
	WCI_Register(&wciMH663);
	CardPort_Register(&mh663Port, Port_Index_PICC);
}

#include "Init.h"

INIT_ENTRY_MAIN(MH663_Init);


